/**
 *******************************************************************************
 * @file  main.c
 * @brief Main program template.
 @verbatim
   Change Logs:
   Date             Author          Notes
   2020-06-30        CDT         First version
 @endverbatim
 *******************************************************************************
 * Copyright (C) 2020, Huada Semiconductor Co., Ltd. All rights reserved.
 *
 * This software component is licensed by HDSC under BSD 3-Clause license
 * (the "License"); You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                    opensource.org/licenses/BSD-3-Clause
 */
/*******************************************************************************
 * Include files
 ******************************************************************************/
/** driver*/
#include <string.h>
#include <math.h>
#include "hc32_ddl.h"
#include "SEGGER_RTT.h"
#include "gpio.hpp"
#include "wdt.hpp"
#include "intflash.hpp"
#include "uartstream.hpp"
#include "commtick.hpp"
/** modules*/
#include "custommeter.hpp"
#include "file.hpp"
#include "firmwaredownload.hpp"
/** systemos*/
#include "threados.hpp"
#include "method.hpp"
#include "streamstation.hpp"
/** app*/
#include "ioapi.hpp"
#include "configapi.hpp"
#include "faultapi.hpp"
#include "recordapi.hpp"
#include "uithread.hpp"
#include "modbusthread.hpp"

using namespace device;
using namespace systemos;
using namespace storage;
using namespace ota;
using namespace measure;

#define MATRIX1                       25
#define MATRIX2                       34
#define SYSTEM_STATUS_ERROR           0x00000001
#define SYSTEM_CALI_COUNT							50
#define SYSTEM_CALI_ERROR_UPPER				1200
#define SYSTEM_CALI_ERROR_LOWER				800

typedef struct
{
    uint16_t SampleBuff[8 * 16];            ///<ADC缓存
    uint16_t EfectiveSampleBuff[8 * 64];		///<ADC缓存2
    CalibrationTPDF tCalibration;           ///<校准参数
    uint32_t uiStatus;                      ///<状态
    uint32_t uiResumeCount;                 ///<复位计数器
		uint32_t uiTripcount;										///<脱扣计数器
    bool bWdtDisable;                       ///<看门狗使能
} MainProcessTPDF;                          ///<过程变量

typedef struct
{
  uint8_t bHappend;                       ///<标记位
  uint16_t usCurrent;                     ///<电流
  uint16_t usPhase;                       ///<相位
	uint32_t uiDelay;
}ShortCircultRecordTPDF;                   ///<短路瞬时事件记录
	
static intflash *mFlash;
static firmwaredownload *mFirmwaredownload;
static stream *mComSendStream;
static stream *mComRecStream;
static stream *mLcdSendStream;
static stream *mLcdRecStream;
static MainProcessTPDF mMainProcess = {0};
static ShortCircultRecordTPDF mShortCircultRecord = {0};
static void MeasureProcess(void);

/**
* @brief        事件记录
* @param[in]    usReason    原因
* @param[in]    usCurrent   电流
* @param[in]    ucPhase     相位
* @retval
*/
static void RecordEvent(uint16_t usReason, uint16_t usCurrent, uint16_t usPhase)
{
    const char *tbl1[] = {"Ig", "Ia", "Ib", "Ic", "In"};
    const char *tbl2[] = {"Block", "Umb", "Earth", "Longdelay", "Shortdelay", "ShortCircuit"};
    uint8_t index1 = usPhase == 0 ? 0 : (usPhase == (1 << 15) ? 1 : (usPhase == (1 << 14) ? 2 : (usPhase == (1 << 13) ? 3 : (usPhase == (1 << 12) ? 4 : 0))));
    uint8_t index2 = usReason == (1 << 6) ? 0 : (usReason == (1 << 7) ? 1 : (usReason == (1 << 8) ? 2 : (usReason == (1 << 9) ? 3 : (usReason == (1 << 10) ? 4 : 5))));
    SEGGER_RTT_printf(0, "Record Event Reason = %s, Current = %d, ucPhase = %s\r\n", tbl2[index2], usCurrent, tbl1[index1]);

    FaultRecordTPDF tRecord;

    tRecord.usCurrent = usCurrent;
    tRecord.usReason = usReason | usPhase;
    RecordEvent(&tRecord);
}

/**
* @brief        定时器1ms
* @retval
*/
bool MainTick(void)
{
	if(mMainProcess.uiTripcount)
	{
		mMainProcess.uiTripcount--;
		if(!mMainProcess.uiTripcount)
		{
			IoApiTrip();
		}
	}
	return(true);
}

/**
* @brief        启动脱扣
* @param[in]    bTrip       是否硬件脱扣
* @param[in]    uiDelay     延时
* @retval
*/
static void StartTrip(bool bTrip, uint32_t uiDelay)
{
	if(bTrip && (uiDelay == 0))
	{
			IoApiTrip();
	}
	if(uiDelay)
	{
		mMainProcess.uiTripcount = uiDelay;
	}
	mMainProcess.uiStatus |= SYSTEM_STATUS_ERROR;
	mMainProcess.uiResumeCount = FAULT_RESUMETIME * 2;
}

/**
 * @brief  通讯处理
 * @retval None
 */
static void CommProcess(void)
{
	static WriteCommandTPDF tCmd;
	WriteStatusTPDF tWriteStatus;
	const keyvalue::KeyDemoTPDF *tKey;
	uint16_t i, j;
	bool bFromLcd = false;
	bool bIrChanged = false;

	/** 检查是否有订阅消息*/
	if(!mComRecStream->Subscribe(&tCmd))
	{
		if(!mLcdRecStream->Subscribe(&tCmd))
		{
			return;
		}
		bFromLcd = true;    ///<消息来自LCD
	}
	switch(tCmd.tType)
	{
		case WRITE_COMMAND_CUSTOMCONFIG:
			for(i = 0; i < tCmd.usLen; i++)
			{
				for(j = 0; j < sizeof(mKeyDemoLcdCustomConfig) / sizeof(keyvalue::KeyDemoTPDF); j++)
				{
					tKey = &mKeyDemoLcdCustomConfig[j];
					if(tKey->uiKey == tCmd.tWriteData[i].uiKey)
					{
						memcpy((uint8_t *)(((uint32_t)&mTarget.tLcdCustomConfig) + tKey->uiOffset),
									 tCmd.tWriteData[i].ucData,
									 tCmd.tWriteData[i].usLen > tKey->usLen ? tKey->usLen : tCmd.tWriteData[i].usLen);
						/** 长延时整定电流被修改*/
						if(tKey->uiKey == LcdCustomConfig_LongDelayCurrent_Attribute.uiKey ||
										tKey->uiKey == LcdCustomConfig_LongDelayEnable_Attribute.uiKey)
						{
							bIrChanged = true;
						}
						break;
					}
				}
			}
			/** 长延时整定电流被修改,将涉及的其余参数进行检查,根据情况恢复默认值*/
			if(bIrChanged)
			{
				CustomConfigDefault(false);
			}
			CustomConfigSet();
			break;
		case WRITE_COMMAND_COMCONFIG:
			for(i = 0; i < tCmd.usLen; i++)
			{
				for(j = 0; j < sizeof(mKeyDemoComConfig) / sizeof(keyvalue::KeyDemoTPDF); j++)
				{
					tKey = &mKeyDemoComConfig[j];
					if(tKey->uiKey == tCmd.tWriteData[i].uiKey)
					{
						memcpy((uint8_t *)(((uint32_t)&mTarget.tComConfig) + tKey->uiOffset),
									 tCmd.tWriteData[i].ucData,
									 tCmd.tWriteData[i].usLen > tKey->usLen ? tKey->usLen : tCmd.tWriteData[i].usLen);
						break;
					}
				}
			}
			ComConfigSet();
			UartChangeParam(mTarget.tComConfig.usBaud, uart::UART_PARITY_TYPE_EVEN);
			break;
		case WRITE_COMMAND_SECURITY:
			for(i = 0; i < tCmd.usLen; i++)
			{
				for(j = 0; j < sizeof(mKeyDemoSecurity) / sizeof(keyvalue::KeyDemoTPDF); j++)
				{
					tKey = &mKeyDemoSecurity[j];
					if(tKey->uiKey == tCmd.tWriteData[i].uiKey)
					{
						memcpy((uint8_t *)(((uint32_t)&mTarget.tSecurityConfig) + tKey->uiOffset),
										 tCmd.tWriteData[i].ucData,
										 tCmd.tWriteData[i].usLen > tKey->usLen ? tKey->usLen : tCmd.tWriteData[i].usLen);
						break;
					}
				}
			}
			SecurityConfigSet();
			break;
		case WRITE_COMMAND_PRODUCTINFOR:
			for(i = 0; i < tCmd.usLen; i++)
			{
				for(j = 0; j < sizeof(mKeyDemoProductInfor) / sizeof(keyvalue::KeyDemoTPDF); j++)
				{
					tKey = &mKeyDemoProductInfor[j];
					if(tKey->uiKey == tCmd.tWriteData[i].uiKey)
					{
						memcpy((uint8_t *)(((uint32_t)&mTarget.tProductInfor) + tKey->uiOffset),
									 tCmd.tWriteData[i].ucData,
									 tCmd.tWriteData[i].usLen > tKey->usLen ? tKey->usLen : tCmd.tWriteData[i].usLen);
						break;
					}
				}
			}
			FactoryConfigSet();
			/** 工厂配置参数改变,保护参数全部恢复默认值*/
			CustomConfigDefault(true);
			CustomConfigSet();
			mMainProcess.bWdtDisable = true;
			break;
		case WRITE_COMMAND_RESET:
			mMainProcess.bWdtDisable = true;
			break;
		case WRITE_COMMAND_CALIBRATION:
			SEGGER_RTT_printf(0, "Calibration!\r\n");
			/** 校准*/
			{
				uint32_t ia = 0,ib = 0,ic = 0,in = 0,ig = 0,z;
				for(i = 0; i < SYSTEM_CALI_COUNT; i++)
				{
					MeasureProcess();
					ia += mTarget.tMeasureData.usIa;
					ib += mTarget.tMeasureData.usIb;
					ic += mTarget.tMeasureData.usIc;
					in += mTarget.tMeasureData.usIn;
					Method::Sleep(20);
				}
				ia /= SYSTEM_CALI_COUNT;
				ib /= SYSTEM_CALI_COUNT;
				ic /= SYSTEM_CALI_COUNT;
				in /= SYSTEM_CALI_COUNT;
				z = ia * 1000 / _PRODUCT_RATEDCURRENT;
				if(z > SYSTEM_CALI_ERROR_LOWER && z < SYSTEM_CALI_ERROR_UPPER)
				{
					mMainProcess.tCalibration.uiIaH = (mMainProcess.tCalibration.uiIaH * 1000 / z);
				}
				z = ib * 1000 / _PRODUCT_RATEDCURRENT;
				if(z > SYSTEM_CALI_ERROR_LOWER && z < SYSTEM_CALI_ERROR_UPPER)
				{
					mMainProcess.tCalibration.uiIbH = (mMainProcess.tCalibration.uiIbH * 1000 / z);
				}
				z = ic * 1000 / _PRODUCT_RATEDCURRENT;
				if(z > SYSTEM_CALI_ERROR_LOWER && z < SYSTEM_CALI_ERROR_UPPER)
				{
					mMainProcess.tCalibration.uiIcH = (mMainProcess.tCalibration.uiIcH * 1000 / z);
				}
				z = in * 1000 / _PRODUCT_RATEDCURRENT;
				if(z > SYSTEM_CALI_ERROR_LOWER && z < SYSTEM_CALI_ERROR_UPPER)
				{
					mMainProcess.tCalibration.uiIn = (mMainProcess.tCalibration.uiIn * 1000 / z);
				}
				CalibrationSet(&mMainProcess.tCalibration);
			}
			break;
		case WRITE_COMMAND_CONTROL:
			SEGGER_RTT_printf(0, "Control Data = %d!\r\n", tCmd.tWriteData[0].ucData[0] + (tCmd.tWriteData[0].ucData[1] << 8));
			/** 试验脱扣*/
			if(tCmd.tWriteData[0].ucData[0] & 0x10)
			{
				IoApiTrip();
			}
			break;
		default:
				break;
	}
	tWriteStatus.bResult = true;
	if(bFromLcd)
	{
			mLcdSendStream->Public(&tWriteStatus);
	}
	else
	{
			mComSendStream->Public(&tWriteStatus);
	}
}

/**
 * @brief  故障处理
 * @retval None
 */
static void FaultProcess(void)
{
	const uint16_t usPhaseTbl[] = {FAULT_RECORD_REASON_ACURRENT, FAULT_RECORD_REASON_BCURRENT, FAULT_RECORD_REASON_CCURRENT};
	FaultCheckResultTPDF* ret = FaultUpdateValue();
	uint32_t vref = mMainProcess.tCalibration.uiVref;
	uint32_t vrealpeak;                                                     ///<短路瞬时尖峰电压

	if(mMainProcess.uiStatus & SYSTEM_STATUS_ERROR)
	{
		if(mMainProcess.uiResumeCount)
		{
			mMainProcess.uiResumeCount--;
			return;
		}
		if(ret->tBlock == fault::FAULT_STATUS_NONE &&
			 ret->tShortDelay == fault::FAULT_STATUS_NONE &&
			 ret->tNShortDelay == fault::FAULT_STATUS_NONE &&
			 ret->tEarth == fault::FAULT_STATUS_NONE &&
			 ret->tLongDelay == fault::FAULT_STATUS_NONE &&
			 ret->tNLongDelay == fault::FAULT_STATUS_NONE &&
			 ret->tUmb == fault::FAULT_STATUS_NONE)
		{
			custommeter::MeterChannel[APP_ADC_IAH_CHANNEL].bLimitEvent = false;
			custommeter::MeterChannel[APP_ADC_IBH_CHANNEL].bLimitEvent = false;
			custommeter::MeterChannel[APP_ADC_ICH_CHANNEL].bLimitEvent = false;
			custommeter::MeterChannel[APP_ADC_IN_CHANNEL].bLimitEvent = false;
			mShortCircultRecord.bHappend = false;
			mMainProcess.uiStatus &= ~SYSTEM_STATUS_ERROR;
			SEGGER_RTT_printf(0, "Fault Resume\r\n");
		}
		else
		{
			StartTrip(true, 0);
		}
	}
	else
	{
		if(mShortCircultRecord.bHappend)
		{
			if(mShortCircultRecord.uiDelay)
			{
				StartTrip(true, mShortCircultRecord.uiDelay);
			}
			else
			{
				StartTrip(false, 0);
			}
			vrealpeak = mShortCircultRecord.usCurrent;
			if(vrealpeak < _COMMON_ATTRIBUTE.uiShortCircuitCurrent)
			{
				vrealpeak = _COMMON_ATTRIBUTE.uiShortCircuitCurrent;
			}
			RecordEvent(FAULT_RECORD_REASON_SHORTCIRCUIT, vrealpeak, mShortCircultRecord.usPhase);
		}
		else if(ret->tBlock == fault::FAULT_STATUS_HAPPEND)
		{
			StartTrip(true, 500);
			RecordEvent(FAULT_RECORD_REASON_BLOCK, _MAX_CURRENT, usPhaseTbl[_MAX_PHASE]);
		}
		else if(ret->tShortDelay == fault::FAULT_STATUS_HAPPEND)
		{
			StartTrip(true, 0);
			RecordEvent(FAULT_RECORD_REASON_SHORTDELAY, _MAX_CURRENT, usPhaseTbl[_MAX_PHASE]);
		}
		else if(ret->tNShortDelay == fault::FAULT_STATUS_HAPPEND)
		{
			StartTrip(true, 0);
			RecordEvent(FAULT_RECORD_REASON_SHORTDELAY, _IN, FAULT_RECORD_REASON_NCURRENT);
		}
		else if(ret->tEarth == fault::FAULT_STATUS_HAPPEND)
		{
			StartTrip(true, 0);
			RecordEvent(FAULT_RECORD_REASON_EARTH, _IGND, 0);
		}
		else if(ret->tLongDelay == fault::FAULT_STATUS_HAPPEND)
		{
			StartTrip(true, _PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_MOTOR? 500:0);
			RecordEvent(FAULT_RECORD_REASON_LONGDELAY, _MAX_CURRENT, usPhaseTbl[_MAX_PHASE]);
		}
		else if(ret->tNLongDelay == fault::FAULT_STATUS_HAPPEND)
		{
			StartTrip(true, _PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_MOTOR? 500:0);
			RecordEvent(FAULT_RECORD_REASON_LONGDELAY, _IN, FAULT_RECORD_REASON_NCURRENT);
		}
		else if(ret->tUmb == fault::FAULT_STATUS_HAPPEND)
		{
			StartTrip(true, 500);
			RecordEvent(FAULT_RECORD_REASON_UNBALANCE, _MAX_CURRENT, usPhaseTbl[_MAX_PHASE]);
		}
	}
}

/**
 * @brief  ADC值超限回调
 * @retval None
 */
static void MeterOutOfLimitCallback(uint8_t ucChannel, uint8_t ucFlag, int32_t iValue)
{
    if(mShortCircultRecord.bHappend)
    {
        return;
    }
    if(ucChannel == APP_ADC_ICH_CHANNEL)
    {
      mShortCircultRecord.usPhase = FAULT_RECORD_REASON_CCURRENT;
			mShortCircultRecord.uiDelay = 0;
    }
    else if(ucChannel == APP_ADC_IBH_CHANNEL)
    {
      mShortCircultRecord.usPhase = FAULT_RECORD_REASON_BCURRENT;
			mShortCircultRecord.uiDelay = 0;
    }
    else if(ucChannel == APP_ADC_IAH_CHANNEL)
    {
			mShortCircultRecord.usPhase = FAULT_RECORD_REASON_ACURRENT;
			mShortCircultRecord.uiDelay = 0;
    }
    else if(ucChannel == APP_ADC_IN_CHANNEL)
    {
			mShortCircultRecord.usPhase = FAULT_RECORD_REASON_NCURRENT;
			if((_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_SWITCH) && _SWITCH_CONFIG.usNCurrent == 5)
			{
				mShortCircultRecord.uiDelay = APP_FAULT_N_DELAY;
			}
			else if((!(_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_SWITCH)) && _LCD_CONFIG.usNCurrent == 5)
			{
				mShortCircultRecord.uiDelay = APP_FAULT_N_DELAY;
			}
			else
			{
				mShortCircultRecord.uiDelay = 0;
			}
    }
		else
		{
			mShortCircultRecord.uiDelay = 0;
		}
    mShortCircultRecord.usCurrent = iValue;
    mShortCircultRecord.bHappend = true;
		if(!mShortCircultRecord.uiDelay)
		{
			IoApiTrip();
		}
}

/**
 * @brief  测量完成回调
 * @retval None
 */
static void MeterConvertedCallback(void)
{
}

/**
 * @brief  更新ADC限值参数
 * @retval None
 */
static void MeasureUpdateShortCircult(void)
{
    uint32_t limit;
    uint32_t vref = mMainProcess.tCalibration.uiVref;   ///<基准电压
    custommeter::calculate::RefreshCalculatePara(mTarget.tProductInfor.usStructCurrent, mTarget.tProductInfor.usCurrent, \
            mTarget.tCommon.uiShortCircuitCurrent, mTarget.tCommon.uiNShortCircuitCurrent);

    if(_COMMON_ATTRIBUTE.bShortCircuitEnable)       ///<ABC瞬时使能
    {
        if(_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_9M45)
        {
            custommeter::MeterChannel[APP_ADC_ICH_CHANNEL].bLimitUpperEnable = true;
            custommeter::MeterChannel[APP_ADC_IBH_CHANNEL].bLimitUpperEnable = true;
            custommeter::MeterChannel[APP_ADC_IAH_CHANNEL].bLimitUpperEnable = true;
        }
        else
        {
            custommeter::MeterChannel[APP_ADC_ICH_CHANNEL].bLimitUpperEnable = true;
            custommeter::MeterChannel[APP_ADC_IBH_CHANNEL].bLimitUpperEnable = true;
            custommeter::MeterChannel[APP_ADC_IAH_CHANNEL].bLimitUpperEnable = true;
        }
    }
    else
    {
        custommeter::MeterChannel[APP_ADC_ICH_CHANNEL].bLimitUpperEnable = false;
        custommeter::MeterChannel[APP_ADC_IBH_CHANNEL].bLimitUpperEnable = false;
        custommeter::MeterChannel[APP_ADC_IAH_CHANNEL].bLimitUpperEnable = false;
    }

    if(_COMMON_ATTRIBUTE.bNShortCircuitEnable)      ///<N相瞬时使能
    {
        if(_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_9M45)
        {
            custommeter::MeterChannel[APP_ADC_IN_CHANNEL].bLimitUpperEnable = true;
        }
        else
        {
            custommeter::MeterChannel[APP_ADC_IN_CHANNEL].bLimitUpperEnable = true;
        }
    }
    else
    {
        custommeter::MeterChannel[APP_ADC_IN_CHANNEL].bLimitUpperEnable = false;
    }
}

/**
 * @brief  测量处理
 * @retval None
 */
static void MeasureProcess(void)
{
	short *i = measure::custommeter::calculate::CurrentBuf;
	uint32_t j, uiStartCurrent = _COMMON_ATTRIBUTE.uiIr * 15 / 100;
	
	if(_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_9M45)
	{
		///<待添加
		
	}
	else
	{
		j = (((uint32_t)i[0]) * mMainProcess.tCalibration.uiIaH) >> APP_PARAM_ADC_SHIFT;
		mTarget.tMeasureData.usIa = j <= uiStartCurrent? 0:j;
		j = (((uint32_t)i[1]) * mMainProcess.tCalibration.uiIbH) >> APP_PARAM_ADC_SHIFT;
    mTarget.tMeasureData.usIb = j <= uiStartCurrent? 0:j;
		j = (((uint32_t)i[2]) * mMainProcess.tCalibration.uiIcH) >> APP_PARAM_ADC_SHIFT;
    mTarget.tMeasureData.usIc = j <= uiStartCurrent? 0:j;
		
		if(_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_4WIRE)
		{
			j = (((uint32_t)i[3]) * mMainProcess.tCalibration.uiIn) >> APP_PARAM_ADC_SHIFT;
			mTarget.tMeasureData.usIn = j <= uiStartCurrent? 0:j;
		}
		else /** 3线无N相电流*/
		{
			mTarget.tMeasureData.usIn = 0;
		}
		/** 拨码型无Ig*/
		if(_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_SWITCH)
		{
			mTarget.tMeasureData.usIgnd = 0;
		}
		else
		{
			j = (((uint32_t)i[4]) * mMainProcess.tCalibration.uiIg) >> APP_PARAM_ADC_SHIFT;
			mTarget.tMeasureData.usIgnd = j <= uiStartCurrent? 0:j;
		}
	}
  /** 更新短路瞬时参数*/
	MeasureUpdateShortCircult();
}

/**
 * @brief  更新通用属性,将拨码，LCD ，电机各种型号统一更新成通用属性
 * @retval None
 */
static void UpdateCommonAttribute(void)
{
	uint32_t IrMult = 0;

	switch(_PRODUCT_ATTRIBUTE & 3)
	{
		case 0: ///<LCD配电型
			/** 长延时*/
			_COMMON_ATTRIBUTE.uiIr = _LCD_CONFIG.usLongDelayCurrent;
			_COMMON_ATTRIBUTE.uiLongDelayCurrent = _LCD_CONFIG.usLongDelayCurrent;
			_COMMON_ATTRIBUTE.uiLongDelayTime = _LCD_CONFIG.usLongDelayTime;
			_COMMON_ATTRIBUTE.bLongDelayEnable = true;
			if(_LCD_CONFIG.usNEnable && (_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_4WIRE))
			{
				_COMMON_ATTRIBUTE.uiNLongDelayCurrent = _PRODUCT_RATEDCURRENT * _LCD_CONFIG.usNCurrent / 10;
				_COMMON_ATTRIBUTE.uiNLongDelayTime = _LCD_CONFIG.usLongDelayTime;
				_COMMON_ATTRIBUTE.bNLongDelayEnable = true;
			}
			else
			{
				_COMMON_ATTRIBUTE.bNLongDelayEnable = false;
			}
			/** 短延时*/
			if(_LCD_CONFIG.usShortDelayEnable)
			{
				_COMMON_ATTRIBUTE.uiShortDelayCurrent = _LCD_CONFIG.usShortDelayCurrent;
				_COMMON_ATTRIBUTE.uiShortDelayTime = _LCD_CONFIG.usShortDelayTime;
				IrMult = (_LCD_CONFIG.usShortDelayCurrent * 1000) / _LCD_CONFIG.usLongDelayCurrent;
				_COMMON_ATTRIBUTE.bShortDelayEnable = true;

				if(_LCD_CONFIG.usNEnable && (_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_4WIRE))
				{
					_COMMON_ATTRIBUTE.uiNShortDelayCurrent = _LCD_CONFIG.usNCurrent * IrMult * _PRODUCT_RATEDCURRENT / 10000;
					_COMMON_ATTRIBUTE.uiNShortDelayTime = _LCD_CONFIG.usShortDelayTime;
					_COMMON_ATTRIBUTE.bNShortDelayEnable = true;
				}
				else
				{
					_COMMON_ATTRIBUTE.bNShortDelayEnable = false;
				}
			}
			else
			{
				_COMMON_ATTRIBUTE.bShortDelayEnable = false;
				_COMMON_ATTRIBUTE.bNShortDelayEnable = false;
			}
			/** 短路瞬时*/
			if(_LCD_CONFIG.usShortCircuitEnable)
			{
				_COMMON_ATTRIBUTE.uiShortCircuitCurrent = _LCD_CONFIG.usShortCircuitCurrent;
				_COMMON_ATTRIBUTE.bShortCircuitEnable = true;

				if(_LCD_CONFIG.usNEnable && (_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_4WIRE))
				{
					_COMMON_ATTRIBUTE.uiNShortCircuitCurrent = _LCD_CONFIG.usShortCircuitCurrent * _LCD_CONFIG.usNCurrent / 10;
					_COMMON_ATTRIBUTE.bNShortCircuitEnable = true;
				}
				else
				{
					_COMMON_ATTRIBUTE.bNShortCircuitEnable = false;
				}
			}
			else
			{
				_COMMON_ATTRIBUTE.bShortCircuitEnable = false;
			}
			/** 接地*/
			if(_LCD_CONFIG.usEarthEnable)
			{
				_COMMON_ATTRIBUTE.uiEarthCurrent = _LCD_CONFIG.usEarthCurrent;
				_COMMON_ATTRIBUTE.uiEarthTime = _LCD_CONFIG.usEarthTime;
				_COMMON_ATTRIBUTE.bEarthEnable = true;
			}
			else
			{
				_COMMON_ATTRIBUTE.bEarthEnable = false;
			}
			break;
		case 1: ///<LCD电机型
			/** 长延时*/
			if(_LCD_CONFIG.usLongDelayEnable)
			{
				_COMMON_ATTRIBUTE.uiIr = _LCD_CONFIG.usLongDelayCurrent;
				_COMMON_ATTRIBUTE.uiLongDelayCurrent = _LCD_CONFIG.usLongDelayCurrent;
				_COMMON_ATTRIBUTE.uiLongDelayTime = _LCD_CONFIG.usLongDelayTime;
				_COMMON_ATTRIBUTE.bLongDelayEnable = true;

				if(_LCD_CONFIG.usNEnable && (_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_4WIRE))
				{
					_COMMON_ATTRIBUTE.uiNLongDelayCurrent = _PRODUCT_RATEDCURRENT * _LCD_CONFIG.usNCurrent / 10;
					_COMMON_ATTRIBUTE.uiNLongDelayTime = _LCD_CONFIG.usLongDelayTime;
					_COMMON_ATTRIBUTE.bNLongDelayEnable = true;
				}
				else
				{
					_COMMON_ATTRIBUTE.bNLongDelayEnable = false;
				}
			}
			else
			{
				_COMMON_ATTRIBUTE.uiIr = _PRODUCT_RATEDCURRENT;
				_COMMON_ATTRIBUTE.bLongDelayEnable = false;
				_COMMON_ATTRIBUTE.bNLongDelayEnable = false;
			}
			/** 短延时*/
			if(_LCD_CONFIG.usShortDelayEnable)
			{
				_COMMON_ATTRIBUTE.uiShortDelayCurrent = _LCD_CONFIG.usShortDelayCurrent;
				_COMMON_ATTRIBUTE.uiShortDelayTime = _LCD_CONFIG.usShortDelayTime;
				IrMult = (_LCD_CONFIG.usShortDelayCurrent * 1000) /
								 (_LCD_CONFIG.usLongDelayEnable ? _LCD_CONFIG.usLongDelayCurrent : _PRODUCT_RATEDCURRENT);
				_COMMON_ATTRIBUTE.bShortDelayEnable = true;

				if(_LCD_CONFIG.usNEnable && (_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_4WIRE))
				{
					_COMMON_ATTRIBUTE.uiNShortDelayCurrent = _LCD_CONFIG.usNCurrent * IrMult * _PRODUCT_RATEDCURRENT / 10000;
					_COMMON_ATTRIBUTE.uiNShortDelayTime = _LCD_CONFIG.usShortDelayTime;
					_COMMON_ATTRIBUTE.bNShortDelayEnable = true;
				}
				else
				{
					_COMMON_ATTRIBUTE.bNShortDelayEnable = false;
				}
			}
			else
			{
				_COMMON_ATTRIBUTE.bShortDelayEnable = false;
				_COMMON_ATTRIBUTE.bNShortDelayEnable = false;
			}
			/** 短路瞬时*/
			_COMMON_ATTRIBUTE.uiShortCircuitCurrent  = 15 * _PRODUCT_RATEDCURRENT;
			_COMMON_ATTRIBUTE.bShortCircuitEnable = true;
			if(_LCD_CONFIG.usNEnable && (_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_4WIRE))
			{
				_COMMON_ATTRIBUTE.uiNShortCircuitCurrent = 15 * _PRODUCT_RATEDCURRENT * _LCD_CONFIG.usNCurrent / 10;
				_COMMON_ATTRIBUTE.bNShortCircuitEnable = true;
			}
			else
			{
				_COMMON_ATTRIBUTE.bNShortCircuitEnable = false;
			}
			/** 接地*/
			if(_LCD_CONFIG.usEarthEnable)
			{
				_COMMON_ATTRIBUTE.uiEarthCurrent = _LCD_CONFIG.usEarthCurrent;
				_COMMON_ATTRIBUTE.uiEarthTime = _LCD_CONFIG.usEarthTime;
				_COMMON_ATTRIBUTE.bEarthEnable = true;
			}
			else
			{
				_COMMON_ATTRIBUTE.bEarthEnable = false;
			}
			/** 相不平衡*/
			if(_LCD_CONFIG.usUnbalanceEnable)
			{
				_COMMON_ATTRIBUTE.uiUnbalanceRated = _LCD_CONFIG.usUnbalanceRated;
				_COMMON_ATTRIBUTE.uiUnbalanceTime = _LCD_CONFIG.usUnbalanceTime;
				_COMMON_ATTRIBUTE.bUnbalanceEnable = true;
			}
			else
			{
				_COMMON_ATTRIBUTE.bUnbalanceEnable = false;
			}
			/** 堵转*/
			if(_LCD_CONFIG.usBlockEnable)
			{
				_COMMON_ATTRIBUTE.uiBlockCurrent = _LCD_CONFIG.usBlockCurrent;
				_COMMON_ATTRIBUTE.uiBlockTime = _LCD_CONFIG.usBlockTime;
				_COMMON_ATTRIBUTE.bBlockEnable = true;
			}
			else
			{
				_COMMON_ATTRIBUTE.bBlockEnable = false;
			}
			break;
		case 2: ///<拨码配电型
			/** 接地*/
			_COMMON_ATTRIBUTE.bEarthEnable = false;
			/** 长延时*/
			_COMMON_ATTRIBUTE.uiIr = _SWITCH_CONFIG.usLongDelayCurrent;
			_COMMON_ATTRIBUTE.uiLongDelayCurrent = _SWITCH_CONFIG.usLongDelayCurrent;
			_COMMON_ATTRIBUTE.uiLongDelayTime = _SWITCH_CONFIG.usLongDelayTime;
			_COMMON_ATTRIBUTE.bLongDelayEnable = true;
			if(_SWITCH_CONFIG.usNCurrent && (_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_4WIRE))
			{
				_COMMON_ATTRIBUTE.uiNLongDelayCurrent = _PRODUCT_RATEDCURRENT * _SWITCH_CONFIG.usNCurrent / 10;
				_COMMON_ATTRIBUTE.uiNLongDelayTime = _SWITCH_CONFIG.usLongDelayTime;
				_COMMON_ATTRIBUTE.bNLongDelayEnable = true;
			}
			else
			{
				_COMMON_ATTRIBUTE.bNLongDelayEnable = false;
			}
			/** 短延时*/
			if(_SWITCH_CONFIG.usShortDelayCurrent)
			{
				_COMMON_ATTRIBUTE.uiShortDelayCurrent = _SWITCH_CONFIG.usShortDelayCurrent * _SWITCH_CONFIG.usLongDelayCurrent / 10;
				_COMMON_ATTRIBUTE.uiShortDelayTime = _SWITCH_CONFIG.usShortDelayTime;
				_COMMON_ATTRIBUTE.bShortDelayEnable = true;
				if(_SWITCH_CONFIG.usNCurrent && (_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_4WIRE))
				{
					_COMMON_ATTRIBUTE.uiNShortDelayCurrent = _SWITCH_CONFIG.usNCurrent * _SWITCH_CONFIG.usShortDelayCurrent * _PRODUCT_RATEDCURRENT / 100;
					_COMMON_ATTRIBUTE.uiNShortDelayTime = _SWITCH_CONFIG.usShortDelayTime;
					_COMMON_ATTRIBUTE.bNShortDelayEnable = true;
				}
				else
				{
					_COMMON_ATTRIBUTE.bNShortDelayEnable = false;
				}
			}
			else
			{
				_COMMON_ATTRIBUTE.bShortDelayEnable = false;
				_COMMON_ATTRIBUTE.bNShortDelayEnable = false;
			}
			/** 短路瞬时*/
			if(_SWITCH_CONFIG.usShortCircuitCurrent)
			{
				_COMMON_ATTRIBUTE.uiShortCircuitCurrent  = _SWITCH_CONFIG.usShortCircuitCurrent * _PRODUCT_RATEDCURRENT;
				_COMMON_ATTRIBUTE.bShortCircuitEnable = true;
				if(_SWITCH_CONFIG.usNCurrent && (_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_4WIRE))
				{
					_COMMON_ATTRIBUTE.uiNShortCircuitCurrent = _COMMON_ATTRIBUTE.uiShortCircuitCurrent  * _SWITCH_CONFIG.usNCurrent / 10;
					_COMMON_ATTRIBUTE.bNShortCircuitEnable = true;
				}
				else
				{
					_COMMON_ATTRIBUTE.bNShortCircuitEnable = false;
				}
			}
			else
			{
				_COMMON_ATTRIBUTE.bShortCircuitEnable = false;
				_COMMON_ATTRIBUTE.bNShortCircuitEnable = false;
			}
			break;
		case 3: ///<拨码电机型
			/** 接地*/
			_COMMON_ATTRIBUTE.bEarthEnable = false;
			/** 长延时*/
			if(_SWITCH_CONFIG.usLongDelayCurrent)
			{
				_COMMON_ATTRIBUTE.uiIr = _SWITCH_CONFIG.usLongDelayCurrent;
				_COMMON_ATTRIBUTE.uiLongDelayCurrent = _SWITCH_CONFIG.usLongDelayCurrent;
				_COMMON_ATTRIBUTE.uiLongDelayTime = _SWITCH_CONFIG.usLongDelayTime;
				_COMMON_ATTRIBUTE.bLongDelayEnable = true;
				if(_SWITCH_CONFIG.usNCurrent && (_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_4WIRE))
				{
					_COMMON_ATTRIBUTE.uiNLongDelayCurrent = _PRODUCT_RATEDCURRENT * _SWITCH_CONFIG.usNCurrent / 10;
					_COMMON_ATTRIBUTE.uiNLongDelayTime = _SWITCH_CONFIG.usLongDelayTime;
					_COMMON_ATTRIBUTE.bNLongDelayEnable = true;
				}
				else
				{
					_COMMON_ATTRIBUTE.bNLongDelayEnable = false;
				}
			}
			else
			{
				_COMMON_ATTRIBUTE.uiIr = _PRODUCT_RATEDCURRENT;
				_COMMON_ATTRIBUTE.bLongDelayEnable = false;
				_COMMON_ATTRIBUTE.bNLongDelayEnable = false;
			}
			/** 短延时*/
			if(_SWITCH_CONFIG.usShortDelayCurrent)
			{
				_COMMON_ATTRIBUTE.uiShortDelayCurrent = (_SWITCH_CONFIG.usLongDelayCurrent ? _SWITCH_CONFIG.usLongDelayCurrent : _PRODUCT_RATEDCURRENT) *
																								_SWITCH_CONFIG.usShortDelayCurrent / 10;
				_COMMON_ATTRIBUTE.uiShortDelayTime = _SWITCH_CONFIG.usShortDelayTime;
				_COMMON_ATTRIBUTE.bShortDelayEnable = true;

				if(_SWITCH_CONFIG.usNCurrent && (_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_4WIRE))
				{
					_COMMON_ATTRIBUTE.uiNShortDelayCurrent = _SWITCH_CONFIG.usNCurrent * _SWITCH_CONFIG.usShortDelayCurrent * _PRODUCT_RATEDCURRENT / 100;
					_COMMON_ATTRIBUTE.uiNShortDelayTime = _SWITCH_CONFIG.usShortDelayTime;
					_COMMON_ATTRIBUTE.bNShortDelayEnable = true;
				}
				else
				{
					_COMMON_ATTRIBUTE.bNShortDelayEnable = false;
				}
			}
			else
			{
				_COMMON_ATTRIBUTE.bShortDelayEnable = false;
				_COMMON_ATTRIBUTE.bNShortDelayEnable = false;
			}
			/** 短路瞬时*/
			_COMMON_ATTRIBUTE.uiShortCircuitCurrent  = 15 * _PRODUCT_RATEDCURRENT;
			_COMMON_ATTRIBUTE.bShortCircuitEnable = true;
			if(_SWITCH_CONFIG.usNCurrent && (_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_4WIRE))
			{
				_COMMON_ATTRIBUTE.uiNShortCircuitCurrent = 15 * _PRODUCT_RATEDCURRENT * _SWITCH_CONFIG.usNCurrent / 10;
				_COMMON_ATTRIBUTE.bNShortCircuitEnable = true;
			}
			else
			{
				_COMMON_ATTRIBUTE.bNShortCircuitEnable = false;
			}
			/** 相不平衡*/
			if(_SWITCH_CONFIG.usUnbalanceRated)
			{
				_COMMON_ATTRIBUTE.uiUnbalanceRated = _SWITCH_CONFIG.usUnbalanceRated;
				_COMMON_ATTRIBUTE.uiUnbalanceTime = _SWITCH_CONFIG.usUnbalanceTime;
				_COMMON_ATTRIBUTE.bUnbalanceEnable = true;
			}
			else
			{
				_COMMON_ATTRIBUTE.bUnbalanceEnable = false;
			}
			break;
	}
}

/**
 * @brief  管理任务
 * @retval None
 */
static void ManageThread(void *args)
{
    uint32_t imax;

    IoApiLedOutput(LED_OUTPUT_GREEN_FLASH);

    while(1)
    {
        if(_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_SWITCH)   ///<拨码规格,更新拨码值
        {
            IoApiSwitchUpdate();
        }

        UpdateCommonAttribute(); ///更新通用属性
        MeasureProcess();   ///>计量流程
        CommProcess();       //通讯接口
        FaultProcess();     //故障查询接口
        /** 黄灯指示*/
        imax = _MAX_CURRENT;

        if(imax >= ((_COMMON_ATTRIBUTE.uiIr * 90) / 100))
        {
            IoApiLedOutput(LED_OUTPUT_YELLOW_ON);
        }
        else if((_IN >= ((_COMMON_ATTRIBUTE.uiNLongDelayCurrent * 90) / 100)) && _COMMON_ATTRIBUTE.bNLongDelayEnable)
        {
            IoApiLedOutput(LED_OUTPUT_YELLOW_ON);
        }
				else
				{
					IoApiLedOutput(LED_OUTPUT_YELLOW_OFF);
				}

        /** 红灯指示*/
        if(imax >= ((_COMMON_ATTRIBUTE.uiIr * 105) / 100))
        {
            IoApiLedOutput(LED_OUTPUT_RED_ON);
        }
				else if((_IN >= ((_COMMON_ATTRIBUTE.uiNLongDelayCurrent * 105) / 100)) && _COMMON_ATTRIBUTE.bNLongDelayEnable)
        {
            IoApiLedOutput(LED_OUTPUT_RED_ON);
        }
        else
        {
            IoApiLedOutput(LED_OUTPUT_RED_OFF);
        }
				/** 背光指示*/
        if(imax >= ((_PRODUCT_RATEDCURRENT * 140) / 100))
        {
            gpio::Write(APP_LCD_AK_PORT,APP_LCD_AK_PIN,1);
        }
				else if((_IN >= ((_PRODUCT_RATEDCURRENT * 140) / 100)) && _COMMON_ATTRIBUTE.bNLongDelayEnable)
        {
            gpio::Write(APP_LCD_AK_PORT,APP_LCD_AK_PIN,1);
        }
        else if(imax <= ((_PRODUCT_RATEDCURRENT * 120) / 100))
        {
            gpio::Write(APP_LCD_AK_PORT,APP_LCD_AK_PIN,0);
					
        }
        Method::Sleep(1);

        if(!mMainProcess.bWdtDisable)
        {
					wdt::Feed();
        }
    }
}

/**
 * @brief  测量初始化
 * @retval None
 */
static void MeasureInit(void)
{
    uint8_t i;
    /** 采样频率3.2k，64点采样，计算周期为16个点*/
    custommeter::SampleBuff = mMainProcess.SampleBuff;
    custommeter::EfectiveSampleBuff = mMainProcess.EfectiveSampleBuff;
    custommeter::ChannelCount = 8;
    custommeter::Frequnce = 3200;
    custommeter::SampleLen = 16;
    custommeter::EfectiveSampleLen = 64;
    custommeter::ValueConvertedCallback = MeterConvertedCallback;
    custommeter::ValueOutOfLimitCallback = MeterOutOfLimitCallback;
    custommeter::MeterChannel[0].tChannel = adc::ADC_CHANNEL_0;
    custommeter::MeterChannel[1].tChannel = adc::ADC_CHANNEL_1;
    custommeter::MeterChannel[2].tChannel = adc::ADC_CHANNEL_2;
    custommeter::MeterChannel[3].tChannel = adc::ADC_CHANNEL_3;
    custommeter::MeterChannel[4].tChannel = adc::ADC_CHANNEL_4;
    custommeter::MeterChannel[5].tChannel = adc::ADC_CHANNEL_5;
    custommeter::MeterChannel[6].tChannel = adc::ADC_CHANNEL_6;
    custommeter::MeterChannel[7].tChannel = adc::ADC_CHANNEL_7;

    for(i = 0; i < 8; i++)
    {
			custommeter::MeterChannel[i].bLimitUpperEnable = false;
    }
    custommeter::calculate::RefreshCalculatePara(mTarget.tProductInfor.usStructCurrent, mTarget.tProductInfor.usCurrent, \
            mTarget.tCommon.uiShortCircuitCurrent, mTarget.tCommon.uiNShortCircuitCurrent);
    MeasureUpdateShortCircult();
    custommeter::Start(adc::ADC_INSTANCE_1, 256, 7);
}

/**
 * @brief  Main function of template project
 * @param  None
 * @retval int32_t return value, if needed
 */
int32_t main(void)
{
    SystemUpdate();
    /** 配置初始化*/
    mFlash = new intflash();
    mFirmwaredownload = new firmwaredownload(mFlash);
    mFirmwaredownload->CheckSumEnable = true;
    /** 检查版本是否有更新*/
    mFirmwaredownload->ReadPrgInfor();

	if(!mFirmwaredownload->PrgInforUseable(&mFirmwaredownload->FirmWareInfor))  ///<一般出现在产品刚下载完程序
	{
		mFirmwaredownload->FirmWareInfor.uiNewVersion = APP_SOFT_VERSION;
		mFirmwaredownload->FirmWareInfor.uiOldVersion = APP_SOFT_VERSION;
		mFirmwaredownload->FirmWareInfor.uiUpdateCount = 0;
		mFirmwaredownload->UpDatePrgInfor();
	}
	else if(mFirmwaredownload->FirmWareInfor.uiNewVersion != mFirmwaredownload->FirmWareInfor.uiOldVersion) ///<出现在OTA升级后
	{
		mFirmwaredownload->FirmWareInfor.uiOldVersion = mFirmwaredownload->FirmWareInfor.uiNewVersion;
		mFirmwaredownload->FirmWareInfor.uiUpdateCount = 0;
		mFirmwaredownload->UpDatePrgInfor();
	}
	file::Init(mFlash);
	FactoryConfigGet();
	IoApiInit();
	CustomConfigGet();
	UpdateCommonAttribute();
	CalibrationGet(&mMainProcess.tCalibration);
	/** 计量初始化*/
	MeasureInit();
	/** 其他配置初始化*/
	ComConfigGet();
	SecurityConfigGet();
	RecordInit();
	memcpy(mTarget.tMyProductInfor.ucSoftDescription, mTarget.tProductInfor.ucSoftDescription, 16);
	mTarget.tMyProductInfor.usCurrent = mTarget.tProductInfor.usCurrent;
	mTarget.tMyProductInfor.usStructCurrent = mTarget.tProductInfor.usStructCurrent;
	/** 消息初始化*/
	mComRecStream = new stream("com/pub", stream::STREAM_DIRECT_SUBSCRIBE, sizeof(WriteCommandTPDF));
	mComSendStream = new stream("com/sbs", stream::STREAM_DIRECT_PUBLIC, sizeof(WriteStatusTPDF));
	mLcdRecStream = new stream("lcd/pub", stream::STREAM_DIRECT_SUBSCRIBE, sizeof(WriteCommandTPDF));
	mLcdSendStream = new stream("lcd/sbs", stream::STREAM_DIRECT_PUBLIC, sizeof(WriteStatusTPDF));
	/** 任务初始化*/
	FaultApiInit();
	streamstation::Init(); ///> 数据中台初始化，接收转发
	UartStreamInit(mTarget.tComConfig.usBaud, uart::UART_PARITY_TYPE_EVEN);
	commtick::RegisteTick(MainTick, 1);

	if(!(_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_SWITCH))    ///<非拨码规格,启动液晶显示任务
	{
			UiThreadInit();
	}

	ModbusThreadInit(mFirmwaredownload);
	threados *t1 = new threados(ManageThread);
	t1->Name = "mng thread";
	t1->Prio = 0;
	t1->StackDeep = 256;
	t1->Start();
	SEGGER_RTT_printf(0, "Started!\r\n");
	/** 启动*/
	wdt::Enable();
	gpio::Write(APP_LED_RED_PORT,APP_LED_RED_PIN,1);
	threados::AppStart();

	while(1)
	{
	}
}

/*******************************************************************************
 * EOF (not truncated)
 ******************************************************************************/
